﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Threading;
using NASA.BeAMartian.Execution;
using NASA.BeAMartian.TagGraph.Surveying;
using System.Windows.Controls.Primitives;
using NASA.BeAMartian.TaskService;
using System.Windows.Media.Imaging;
using NASA.BeAMartian.Model;
using NASA.BeAMartian.DallasService;
using System.IO;
using NASA.BeAMartian.Controls;

namespace NASA.BeAMartian.Views.Participate
{
    public partial class RoverTagging : PhoneApplicationPage
    {
        private int roverID = 1;
        public event EventHandler<EventArgs> TaggingFinished;
        private string roverName;
        Tags tagGraph = new Tags();
        List<ImageFeature> taggedFeatures = new List<ImageFeature>();

        ExecutionQueue currentExecutionQueue = null;
        private ExecutionQueue CurrentExecutionQueue
        {
            get
            {
                if (this.currentExecutionQueue == null)
                {
                    this.currentExecutionQueue = new ExecutionQueue();
                }

                return this.currentExecutionQueue;
            }
        }

        public bool IsProcessing
        {
            set
            {
                if (value)
                {
                    this.pbLoadingBar.Opacity = 1.0;
                    this.pbLoadingBar.IsIndeterminate = true;
                }
                else
                {
                    this.pbLoadingBar.Opacity = 0;
                    this.pbLoadingBar.IsIndeterminate = false;
                }
            }
        }

        public RoverTagging()
        {
            InitializeComponent();
            tbCamera.Text = "";
            tbSite.Text = "";
            tbSol.Text = "";
            tbRover.Text = "";
            ApplicationContext.Instance.MapRoomTaskSequence = 1;

            Loaded += new RoutedEventHandler(RoverSurveying_Loaded);            
            tags = new ImageFeatures();
            ToggleUncheckedHandlers(true);
        }

        void RoverSurveying_Loaded(object sender, RoutedEventArgs e)
        {
            Random random = new Random(DateTime.Now.Millisecond);
            roverID = random.Next(1, 3);

            tbCamera.Text = "";
            tbSite.Text = "";
            tbSol.Text = "";
            tbRover.Text = "";

            if (roverID == 2)
                roverName = "Spirit";
            else
                roverName = "Opportunity";

            tbRover.Text = String.Format("Mars Rover {0}", roverName);
            this.LoadData();

            taggedFeatures.Clear();
            tbRover_Copy.Text = String.Format("Image {0} of 3", ApplicationContext.Instance.MapRoomTaskSequence);
        }

        void imgRoverPicture_ImageOpened(object sender, RoutedEventArgs e)
        {
            startApp();
        }

        private void LoadData()
        {
            TaskServiceClient client = new TaskServiceClient("BasicHttpBinding_ITaskService");
            ServiceClientExecutionItem<ITaskService, GetNextSurveyingTaskCompletedEventArgs> actionItem =
                    new ServiceClientExecutionItem<ITaskService, GetNextSurveyingTaskCompletedEventArgs>(
                        client,
                        () => client.GetNextSurveyingTaskAsync(roverID),
                        (EventHandler<GetNextSurveyingTaskCompletedEventArgs> handler) => client.GetNextSurveyingTaskCompleted += handler,
                        (EventHandler<GetNextSurveyingTaskCompletedEventArgs> handler) => client.GetNextSurveyingTaskCompleted -= handler,
                        (s, e) => client_GetNextSurveyingTaskCompleted(s, e),
                        1,
                        () => ph = true,
                        () => ph = false
                    );

            this.CurrentExecutionQueue.Enqueue(actionItem);
            this.CurrentExecutionQueue.Run();
        }

        bool ph;

        private void client_GetNextSurveyingTaskCompleted(object sender, GetNextSurveyingTaskCompletedEventArgs e)
        {
            if (e.Error != null)
                throw e.Error;

            if (e.Cancelled != true)
            {
                this.LoadData(e.Result);
            }
        }

        private void LoadData(RoverImageMetaData metadata)
        {
            tbCamera.Text = metadata.Instrument;
            tbSite.Text = metadata.Site.ToString();
            tbSol.Text = metadata.MarsSol.ToString();
            imgRoverPicture.ImageOpened += new EventHandler<RoutedEventArgs>(imgRoverPicture_ImageOpened);

             imgRoverPicture.Source = new BitmapImage(
                    new Uri(String.Format("http://pic2009.blob.core.windows.net/merimages/{0}", metadata.ImageId)));
        }

        void startApp()
        {
            IsProcessing = false;

            ((Storyboard)Resources["sbOpenImage"]).Begin();
            LocationText.Visibility = System.Windows.Visibility.Visible;
        }
        
        private void client_GetMerImageCompleted(object sender, GetMerImageCompletedEventArgs e)
        {
            this.IsProcessing = false;

            if (e.Error != null)
                throw e.Error;

            if (e.Cancelled != true)
            {               
                BitmapImage bitmap = new BitmapImage();
                bitmap.SetSource(new MemoryStream(e.Result));

                imgRoverPicture.Source = bitmap;
            }
        }

        private void DoneButton_Click(object sender, RoutedEventArgs e)
        {
           
        }

        void setSummaryTags(ListBox lb, string cat, bool catIsVisible)
        {

            string s = "";
            foreach (ImageFeature i in lb.ItemsSource)
            {
                ListBoxItem lbi2 = (ListBoxItem)(lb.ItemContainerGenerator.ContainerFromItem(i));
                if (Utils.VisualTreeUtils.FindChildByType<ToggleButton>(lbi2).IsChecked.Value)
                {
                    if (s.Length > 0)
                        s += ", ";
                    s += i.Feature;
                }
            }

            ((TextBlock)FindName(String.Format("tbSummary{0}Visible", cat))).Text = catIsVisible ? "Yes" : "No";

            if (s.Length == 0)
            {
                ((TextBlock)FindName(String.Format("tbSummary{0}Features", cat))).Visibility = System.Windows.Visibility.Collapsed;
                ((TextBlock)FindName(String.Format("tbSummary{0}FeaturesLabel", cat))).Visibility = System.Windows.Visibility.Collapsed;
            }
            else
            {
                ((TextBlock)FindName(String.Format("tbSummary{0}Features", cat))).Visibility = System.Windows.Visibility.Visible;
                ((TextBlock)FindName(String.Format("tbSummary{0}FeaturesLabel", cat))).Visibility = System.Windows.Visibility.Visible;
                ((TextBlock)FindName(String.Format("tbSummary{0}Features", cat))).Text = s;
            }
        }

        private void HelpButton_Click(object sender, RoutedEventArgs e)
        {

        }

        private ImageFeatures tags;

        private string Cat(string cat, string catType)
        {
            return String.Format("cb{0}{1}", cat, catType);
        }

        private void rbFeature_Checked(object sender, EventArgs e)
        {
            //Don't allow any tagging while in classifying mode
            imgRoverPicture.IsHitTestVisible = false;
            string el = (sender as ToggleButton).Tag as string;

            if (DataContext != null && ((ImageTagTypes)DataContext).ToString() != el)
            {
                switch ((ImageTagTypes)DataContext)
                {
                    case ImageTagTypes.Land:
                        categoryButtonLand.tb.IsChecked = null;
                        break;
                    case ImageTagTypes.Sky:
                        categoryButtonSky.tb.IsChecked = null;
                        break;
                    case ImageTagTypes.Rover:
                        categoryButtonRover.tb.IsChecked = null;
                        break;
                }
            }

            DataContext = (ImageTagTypes)Enum.Parse(typeof(ImageTagTypes), el, true);
            switchCategory(true);

        }

        private void rbFeature_Unchecked(object sender, EventArgs e)
        {
            ImageTagTypes oldSelection = ImageTagTypes.Unknown;

            if(DataContext != null)
                oldSelection = (ImageTagTypes)DataContext;

            ImageTagTypes newSelection = (ImageTagTypes)Enum.Parse(typeof(ImageTagTypes), (sender as ToggleButton).Tag as string, true);

            if (oldSelection == newSelection)
            {
                clearTags(newSelection);
                resetTagCount(newSelection);
                switchCategory(false);
                DataContext = null;
            }
            else
            {
                (sender as ToggleButton).IsChecked = true;
                DataContext = newSelection;
            }
            
        }

        void switchCategory(bool on)
        {
            ImageTagTypes tagType = ImageTagTypes.Unknown;

            if(DataContext != null)
                tagType = (ImageTagTypes)DataContext;
            
            if (on)
            {
                if(cnvImage.Children.Contains(tagGraph))
                    cnvImage.Children.Remove(tagGraph);

                Dispatcher.BeginInvoke(() =>
                {
                    IsHitTestVisible = false;
                    tagGraph = new Tags();
                    tagGraph.onTagSelected -= new EventHandler<TagSelectedEventArgs>(tagGraph_onTagSelected);
                    tagGraph.onTagSelected += new EventHandler<TagSelectedEventArgs>(tagGraph_onTagSelected);
                    tagGraph.TagsFormed -= new EventHandler<EventArgs>(tagGraph_TagsFormed);
                    tagGraph.TagsFormed += new EventHandler<EventArgs>(tagGraph_TagsFormed);
                    Canvas.SetLeft(tagGraph, -360);
                    Canvas.SetTop(tagGraph, 0);
                    cnvImage.Children.Add(tagGraph);
                    tagGraph.Load(roverName, tagType, taggedFeatures);
                }
                );

            }
            else
            {
                if (tagGraph != null && tagGraph.TagType == tagType)
                    cnvImage.Children.Remove(tagGraph);
            }
        }

        void tagGraph_TagsFormed(object sender, EventArgs e)
        {
            IsHitTestVisible = true;
        }

        void tagGraph_onTagSelected(object sender, TagSelectedEventArgs e)
        {
            if (taggedFeatures.Contains(e.Feature))
                return;

            e.Feature.IsSelected = true;
            taggedFeatures.Add(e.Feature);

            resetTagCount(e.Feature.TagType);
        }

        void resetTagCount(ImageTagTypes itt)
        {
            int tagCount = getFeatureCount(itt);

            switch (itt)
            {
                case ImageTagTypes.Land:
                    categoryButtonLand.TagCount = String.Format("({0} of 7)", tagCount);
                    break;
                case ImageTagTypes.Sky:
                    categoryButtonSky.TagCount = String.Format("({0} of 4)", tagCount);
                    break;
                case ImageTagTypes.Rover:
                    categoryButtonRover.TagCount = String.Format("({0} of 6)", tagCount);
                    break;
            }
        }

        int getFeatureCount(ImageTagTypes itt)
        {
            return (
                from feature in taggedFeatures
                where feature.TagType == itt
                select feature).Count();
        }

        void setToggleBottonEnabledFlag(ListBox lb, bool on)
        {
            foreach (ImageFeature i in lb.ItemsSource)
            {
                ListBoxItem lbi2 = (ListBoxItem)(lb.ItemContainerGenerator.ContainerFromItem(i));
                Utils.VisualTreeUtils.FindChildByType<ToggleButton>(lbi2).IsEnabled = on;
            }
        }

        void unCheckTagList(ListBox lb)
        {
            foreach (ImageFeature i in lb.ItemsSource)
            {
                ListBoxItem lbi2 = (ListBoxItem)(lb.ItemContainerGenerator.ContainerFromItem(i));
                Utils.VisualTreeUtils.FindChildByType<ToggleButton>(lbi2).IsChecked = false;
            }
        }

        void clearTags(ImageTagTypes itt)
        {
            for (int i = taggedFeatures.Count - 1; i >= 0; i--)
            {
                if (taggedFeatures[i].TagType == itt)
                    taggedFeatures.RemoveAt(i);
            }
        }

        void ToggleUncheckedHandlers(bool on)
        {
            if (on)
            {
                categoryButtonLand.tb.Checked += rbFeature_Checked;
                categoryButtonLand.tb.Unchecked += rbFeature_Unchecked;

                categoryButtonSky.tb.Checked += rbFeature_Checked;
                categoryButtonSky.tb.Unchecked += rbFeature_Unchecked;

                categoryButtonRover.tb.Checked += rbFeature_Checked;
                categoryButtonRover.tb.Unchecked += rbFeature_Unchecked;
            }
            else
            {
                categoryButtonLand.tb.Checked -= rbFeature_Checked;
                categoryButtonLand.tb.Unchecked -= rbFeature_Unchecked;

                categoryButtonSky.tb.Checked -= rbFeature_Checked;
                categoryButtonSky.tb.Unchecked -= rbFeature_Unchecked;

                categoryButtonRover.tb.Checked -= rbFeature_Checked;
                categoryButtonRover.tb.Unchecked -= rbFeature_Unchecked;
            }
        }

        private void InfoIcon_MouseEnter(object sender, TagSelectedEventArgs e)
        {
            
            ImageFeature f = e.Feature;
            ((Storyboard)Resources["sbOpenHelp"]).Begin();
            
        }

        private void InfoIcon_MouseLeave(object sender, TagSelectedEventArgs e)
        {
            ((Storyboard)Resources["sbOpenHelp"]).Stop();
        }

        private void resetTagger()
        {
            ToggleUncheckedHandlers(false);
            DataContext = null;
            categoryButtonLand.TagCount = "(0 of 7)";
            categoryButtonSky.TagCount = "(0 of 4)";
            categoryButtonRover.TagCount = "(0 of 6)";
            categoryButtonLand.tb.IsChecked = false;
            categoryButtonRover.tb.IsChecked = false;
            categoryButtonSky.tb.IsChecked = false;
            taggedFeatures.Clear();
            ToggleUncheckedHandlers(true);
        }

        private void cnvImage_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            FrameworkElement fe = e.OriginalSource as FrameworkElement;
            InfoIcon ii = Utils.VisualTreeUtils.FindParentByType<InfoIcon>(fe);
            if (ii != null)
            {
                ImageTagTypes itt = (ImageTagTypes)DataContext;
                switch (itt)
                {
                    case ImageTagTypes.Land:
                        RoverTagLand rtl = Utils.VisualTreeUtils.FindParentByType<RoverTagLand>(ii);
                        MessageBox.Show(rtl.ImageTag.FeatureLong + ": " + rtl.ImageTag.Description);
                        break;
                    case ImageTagTypes.Sky:
                        RoverTagSky rts = Utils.VisualTreeUtils.FindParentByType<RoverTagSky>(ii);
                        MessageBox.Show(rts.ImageTag.FeatureLong + ": " + rts.ImageTag.Description);
                        break;
                    case ImageTagTypes.Rover:
                        RoverTagRover rtr = Utils.VisualTreeUtils.FindParentByType<RoverTagRover>(ii);
                        MessageBox.Show(rtr.ImageTag.FeatureLong + ": " + rtr.ImageTag.Description);
                        break;
                }
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            nextImage();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            nextImage();
        }

        void nextImage()
        {
            if (ApplicationContext.Instance.MapRoomTaskSequence < 3)
            {
                if (DataContext != null && DataContext.GetType() == typeof(ImageTagTypes))
                {
                    ImageTagTypes tagType = (ImageTagTypes)DataContext;
                    if (cnvImage.Children.Contains(tagGraph))
                        cnvImage.Children.Remove(tagGraph);
                }

                resetTagger();
                ApplicationContext.Instance.MapRoomTaskSequence += 1;
                RoverSurveying_Loaded(this, null);
            }
            else
            {
                if (TaggingFinished != null)
                    TaggingFinished(this, null);

                SaveTask();
            }
        }

        private void SaveTask()
        {
            //default to anonymous user
            int userID = 772880;

            if (ApplicationContext.Instance.UserData != null && ApplicationContext.Instance.UserData.UserID != 0)
                userID = int.Parse(ApplicationContext.Instance.UserData.UserID.ToString());

            TaskServiceClient client = new TaskServiceClient("BasicHttpBinding_ITaskService");
            //client.SaveCraterTaskDataAsync
            ServiceClientExecutionItem<ITaskService, SaveRoverTaggingTaskDataCompletedEventArgs> actionItem =
                new ServiceClientExecutionItem<ITaskService, SaveRoverTaggingTaskDataCompletedEventArgs>(
                    client,
                    () => client.SaveRoverTaggingTaskDataAsync(userID, new List<GalaxyZoo.Client.Model.Metadata>(0), new List<object>()),
                    (EventHandler<SaveRoverTaggingTaskDataCompletedEventArgs> handler) => client.SaveRoverTaggingTaskDataCompleted += handler,
                    (EventHandler<SaveRoverTaggingTaskDataCompletedEventArgs> handler) => client.SaveRoverTaggingTaskDataCompleted -= handler,
                    (s, e) => SaveTaskCompleted(s, e),
                    1,
                    () => this.IsProcessing = true,
                    () => this.IsProcessing = false
                );

            this.CurrentExecutionQueue.Enqueue(actionItem);
            this.CurrentExecutionQueue.Run();
        }

        private void SaveTaskCompleted(object sender, SaveRoverTaggingTaskDataCompletedEventArgs e)
        {
            this.IsProcessing = false;

            if (e.Error != null)
                throw e.Error;

            if (e.Cancelled == true)
                return;

            ApplicationContext.Instance.TaggingTaskData = e.Result;
            Utils.VisualTreeUtils.FindParentByType<MapRoom>(this).NavigationService.Navigate(new Uri("/Views/Participate/RoverTaggingTaskCompleted.xaml", UriKind.RelativeOrAbsolute));
        }
    }

}
